package utils

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"fmt"
	"io"
)

func SHA1Encode(src string) string {
	t := sha1.New()
	_, _ = io.WriteString(t, src)
	return fmt.Sprintf("%x", t.Sum(nil))
}

func GetPublicKey(publicKey []byte) (*rsa.PublicKey, error) {
	block, _ := pem.Decode(publicKey)
	if block == nil {
		return nil, errors.New("public key error")
	}
	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	return pubInterface.(*rsa.PublicKey), nil
}

func GetPrivateKey(privateKey []byte) (*rsa.PrivateKey, error) {
	block, _ := pem.Decode(privateKey)
	if block == nil {
		return nil, errors.New("private key error")
	}
	return x509.ParsePKCS1PrivateKey(block.Bytes)
}

func RsaEncrypt(data []byte, publicKey *rsa.PublicKey) ([]byte, error) {
	return rsa.EncryptPKCS1v15(rand.Reader, publicKey, data)
}

func RsaDecrypt(cipherData []byte, privateKey *rsa.PrivateKey) ([]byte, error) {
	return rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherData)
}

func AesEncrypt(origData, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	origData = PKCS5Padding(origData, blockSize)
	// 使用密钥的前blockSize个字节作为IV
	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
	crypted := make([]byte, len(origData))
	blockMode.CryptBlocks(crypted, origData)
	return crypted, nil
}

// AesDecrypt 使用AES-CBC模式解密数据，使用密钥的前BlockSize个字节作为IV
func AesDecrypt(crypted, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	// 使用密钥的前blockSize个字节作为IV (保持原有逻辑)
	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
	origData := make([]byte, len(crypted))
	blockMode.CryptBlocks(origData, crypted)
	// 移除填充
	origData = PKCS5UnPadding(origData)
	return origData, nil
}

// PKCS5Padding 添加PKCS#5填充
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padText...)
}

// PKCS5UnPadding 移除PKCS#5填充
func PKCS5UnPadding(origData []byte) []byte {
	length := len(origData)
	if length == 0 {
		return origData
	}
	// 获取填充值
	unPadding := int(origData[length-1])
	// 确保填充值有效
	if unPadding > length {
		return origData // 如果填充值无效，返回原始数据
	}
	return origData[:(length - unPadding)]
}

func APHash(key string) uint32 {
	var hash uint32
	for i, char := range key {
		if i&1 == 0 {
			hash ^= (hash << 7) ^ uint32(char) ^ (hash >> 3)
		} else {
			hash ^= ^((hash << 11) ^ uint32(char) ^ (hash >> 5))
		}
	}
	return hash & 0x7FFFFFFF
}
